var Util = require('../Util/Util').Util;
var Animation = require('../Animation').Animation;
var Scale = require('../Util/Scaler').Scale;

exports.VerticalPagedBrowserOptions = Core.Class.subclass ({
/** @lends Browser.VerticalPagedBrowserOptions.prototype */
	
	classname: 'VerticalPagedBrowserOptions',
	
	/**
	 * @class Options for the page browser
	 * Parameters include blocksPerPage, topMargin, browserSize, origin
	 * 
	 * @constructs The default constructor.
	 * @augments Core.Class
	 */
	initialize: function() {
		this.blocksPerPage = 4;
		this.topMargin = 0;
		this.browserSize = Util.screenSize(true);
		this.origin = new Core.Vector(0,0);
	},
	
});

exports.VerticalPagedBrowser = Animation.AANode.subclass ({
/** @lends Browser.VerticalPagedBrowser.prototype */
	
	classname: 'VerticalPagedBrowser',
	
	/** 
	 * Enumeration for PagedBrowser states
	 * @namespace
	 */
	State: {
		/** Idle */
		Idle: 0,
		/** Swiping in the Browser */
		Swiping: 1,
	},
	
	/**
	 * @class A swipable browser that is paged and can have a page indicator attached to it.
	 * @param {Core.Size} blockSize The size for each block in the browser
	 * @param {Array} blocks The blocks for the browser
	 * @param {Browser.PagedBrowserOptions} options The browser options
	 * @constructs The default constructor.
	 * @augments Animation.AANode
	 */
	initialize: function(blockSize, blocks, options, callback) {
		var self = this;
		this.state = this.State.Idle;
		this.activePage = 0;
		this.blockSize = blockSize;
		this.blocks = blocks;
		this.options = options;
		this._callback = callback;
		this.updateNumberOfPages();
		
		this.setPosition(this.options.origin.clone());
		
		this.touchTarget = new GL2.TouchTarget();
		this.touchTarget.setSize(this.options.browserSize);
		this.touchTarget.setAnchor(new Core.Point(0,0));
		this.touchTarget.setPosition(this.getPosition().clone());
		
		this.scrollTouchHandler = new this.BrowserScrollTouchHandler(this);
		this.touchTarget.getTouchEmitter().addListener(this.scrollTouchHandler, this.scrollTouchHandler.onTouch);
		
		this.initializeBlocks();
		if(this._callback){
	 			if(this.numPages==1)
	 				this._callback(false,false,0);
	 			else if(this.activePage==0)
	 				this._callback(false,true,0);
	 			else if(this.activePage==((this.numPages-1)*1))
	 				this._callback(true,false,0);
	 			else
	 				this._callback(true,true,0);
	 		}
	},
	
	/**
	 * Gets the touch target for this browser
	 * @returns {GL2.TouchTarget} The touch target
	 */
	getTouchTarget: function(){
        return this.touchTarget;
    },
	
	/**
	 * Set the page indicator for this browser.
	 * The indicator should implement setMaxPages and setCurrentPage
	 * @param {Object} pi The page indicator
	 */
	setPageIndicator: function(pi) {
		
		this.pageIndicator = pi;
		this.pageIndicator.setMaxPages(this.numPages);
		this.pageIndicator.setCurrentPage(this.activePage + 1);
	},

	/**
	 * Set the page action for this browser.
	 * @param {Object} pi The page indicator
	 */
	setPageAction: function(pa) {
		
		this.pageAction = pa;
	},
	
	/**
	 * Updates the number of pages for this browser
	 * @private
	 */
	updateNumberOfPages: function() {
		
		if (!this.blocks || this.blocks.length == 0)
			this.numPages = 1;
		else {
			this.numPages = Math.floor(this.blocks.length / this.options.blocksPerPage);
			if ((this.blocks.length % this.options.blocksPerPage) != 0)
				this.numPages++;
		}
	},
	
	/**
	 * Goes through each block and places them appropriately in each page of the browser
	 * @private
	 */
	initializeBlocks: function() {
		
		this.currentPopulatePage = 0;
		this.currentPopulateBlock = 0;
		
		var browserSize = this.options.browserSize;
		
		var columns = Math.floor(browserSize.getWidth() / this.blockSize.getWidth());
		var rows = Math.floor(browserSize.getHeight() / this.blockSize.getHeight());
		
		var xPixels = browserSize.getWidth() / columns;
		var yPixels = (browserSize.getHeight() - this.options.topMargin) / rows;
		
		var xOffset = xPixels / 2;
		var yOffset = yPixels / 2;
		
		if (!this.blocks) return;
		for (var i in this.blocks) {
			var block = this.blocks[i];
			
			this.currentPopulatePage = Math.floor(this.currentPopulateBlock / this.options.blocksPerPage);
			
			var currentBlockOnThisPage = this.currentPopulateBlock % this.options.blocksPerPage;
			
			var column = Math.floor(currentBlockOnThisPage / columns);
			var row = currentBlockOnThisPage % columns;
		
			block.setScale(0.97, 0.97);
			//console.log("adding Blocks: " + i);
			block.setPosition(Scale.width((((i%4) * 103) + 21)), Scale.height((Math.floor((i/4)) * 114) + 10));
			if((i%4)==0 ){
				//console.log("inside Line:aqif");
				var bottomLine = new AASprite();
		        var a = new GL2.Animation();
		        a.pushFrame(AtlasMap.getAnimationFrame('frame_line.png'));
		        a.setBlendEnabled(false);
		        bottomLine.setAnimation(a);
		        bottomLine.setScale(0.87, 1);
				bottomLine.setPosition(Scale.width(((i%4) * 107) + 183), Scale.height((Math.floor(((i)/4)) * 114) + 65));
				this.addChild(bottomLine);
			}
		
			this.currentPopulateBlock++;
			
			this.addChild(block);
		}
	},
	
	

	/**
	 * Adds a block to the end position of this browser
	 * @param {Object} block The block to add
	 */
	addBlock: function(block) {
		
		var browserSize = this.options.browserSize;
		
		var columns = Math.floor(browserSize.getWidth() / this.blockSize.getWidth());
		var rows = Math.floor(browserSize.getHeight() / this.blockSize.getHeight());
		
		var xPixels = browserSize.getWidth() / columns;
		var yPixels = (browserSize.getHeight() - this.options.topMargin) / rows;
		
		var xOffset = xPixels / 2;
		var yOffset = yPixels / 2;
		
		this.currentPopulatePage = Math.floor(this.currentPopulateBlock / this.options.blocksPerPage);
		
		var currentBlockOnThisPage = this.currentPopulateBlock % this.options.blocksPerPage;
		
		var row = Math.floor(currentBlockOnThisPage / columns);
		var column = currentBlockOnThisPage % columns;
		
		var xPos = browserSize.getWidth() * this.currentPopulatePage + (column*xPixels + xOffset)
		var yPos = (rows-1-row) * yPixels + yOffset - this.options.topMargin;
			
		block.setPosition(xPos, yPos);
		this.currentPopulateBlock++;
			
		this.addChild(block);
		this.blocks.push(block);
		
		this.updateOnAddRemoveBlock();
	},
	
	/**
	 * Removes a single block from this browser
	 * @param {Object} removeBlock
	 */
	removeBlock: function(removeBlock) {
		
		var array = [];
		array.push(removeBlock);
		this.removeBlocks(array);
	},
	
	makeOnlyCurrentVisible: function(){
		
	},
	
	/**
	 * Removes multiple blocks from this browser and reorganizes all block positions
	 * @param {Array} removeBlocks
	 */
	removeBlocks: function(removeBlocks) {
		
		if (!removeBlocks || removeBlocks.length == 0) return;
		
		for (var i in removeBlocks) {
			
			var removeBlock = removeBlocks[i];
			this.removeChild(removeBlock);
			Util.removeByValue(this.blocks, removeBlock);
		}
		
		for (var i in this.blocks) {
			this.removeChild(this.blocks[i]);
		}
		
		this.initializeBlocks();
		this.updateOnAddRemoveBlock();
		
		if (this.activePage == this.numPages && this.numPages > 0)
			this.slideToPage(this.activePage - 1);
	},
	
	getBlocks: function() {
		return this.blocks;
	},
	
	/**
	 * Performs internal data updates when blocks have been removed or added to the Browser
	 * @private
	 */
	updateOnAddRemoveBlock: function() {
		
		//this.updateNumberOfPages();
		
		if (this.pageIndicator) {
			
			this.pageIndicator.setMaxPages(this.numPages);
			this.pageIndicator.setCurrentPage(this.activePage + 1);
		}
		
		// TODO: Update browser size
	},
	
	/**
	 * Animates a change to the specified page
	 * @param {int} page The page to slide to
	 */
	
	resetPosition: function(){
		var newPosition = new Core.Vector(this.options.origin.getX() ,this.options.origin.getY());
		this.setPosition(newPosition);
	},
	
	slideToPage: function(page) {
		
		NgLogD("Sliding To Page " + page);
		if(this._callback && (page < 0 || page>((this.numPages-1)*1)) ){
 			return;
 		}
		var slidePos = new Core.Vector( this.getPosition().getX(), this.options.browserSize.getHeight() * page * -1 + this.options.origin.getY()); //X
		NgLogD("Slide Position " + slidePos.getX() + ", " + slidePos.getY());
		var slideAction = new Animation.AAMoveTo(slidePos, 0.3);
		var slideActionEase = new Animation.AAEaseOut(slideAction, 2);
		
		var thisBrowser = this;
		var callback = new Animation.AACallFuncND(function() { thisBrowser.onSlidToPage(page) });
		
		this.runAction(new Animation.AASequence(slideAction, callback));
	},
	
	/**
	 * Callback when slideToPage animation has completed
	 * @private
	 * @param {Object} page The page slid to
	 */
	onSlidToPage: function(page) {
		
		NgLogD("On Slid To Page " + page);
		
		this.activePage = page;
		this.state = this.State.Idle;
 		if(this._callback){
 			if(this.numPages==1)
 				this._callback(false,false,this.activePage);
 			else if(this.activePage==0)
 				this._callback(false,true,this.activePage);
 			else if(this.activePage==((this.numPages-1)*1)  )
 				this._callback(true,false,this.activePage);
 			else
 				this._callback(true,true,this.activePage);
 		}
 		if (this.pageIndicator) {
			this.pageIndicator.setCurrentPage(this.activePage + 1);
		}
 		if (this.pageAction) {
			this.pageAction.setHighlighted(this.activePage);
		}

	},
	
	destroy: function($super) {
		
		for (var i = this._children.length - 1; i >= 0; i--) {
			this._children[i].destroy();
		}
		$super();
	},
	
	$BrowserScrollTouchHandler: Core.MessageListener.subclass({
		
		initialize: function(browser) {
			
			this._browser = browser;
			this._target = browser.getTouchTarget();
		},
		
		onTouch: function(touch) {
			
			switch (touch.getAction()) {
				
				case touch.Action.Start:
					
					
					if (this._trackingId != touch.getId()) {
						this._previoustouchedBlock = this._touchedBlock;
					}
					else this._previoustouchedBlock = null;
					
					this._trackingId = touch.getId();
					this._trackingCurrent = touch.getPosition();
					this._swipeStartX = touch.getPosition().getX();		// swiped X
					this._swipeStartY = touch.getPosition().getY();
					
					this._browser.stopAllActions();
				
					var local = this._browser.getParent().screenToLocal(this._trackingCurrent);
                    var current = this._browser.getPosition();
                    
                    this._originalPosition = this._browser.getPosition().clone();
                    
                    //offset of the actual difference between the point of touch and the current position of tilemap
                    this._trackingOffset = new Core.Vector(current.getX() - local.getX(), current.getY() - local.getY());
				
					return true;
				case touch.Action.End:
				
					if (this._trackingId != touch.getId()) 
					{
						if (this._previoustouchedBlock)
							this._previoustouchedBlock.inactivate();
                        return;
					}
					
					this._trackingId = NaN;
				
					var state = this._browser.state;
					if (state == this._browser.State.Idle) {
						for (var i = 0; i < this._browser.blocks.length; i++) {
							if (this._browser.blocks[i].getTouchTarget &&
								touch.getIsInside(this._browser.blocks[i].getTouchTarget())) {
								if (typeof this._browser.blocks[i].touchedBlock != 'undefined') this._browser.blocks[i].touchedBlock(); 
							}
						}
						
					}
					
					if (state == this._browser.State.Swiping) {
						
						var activePage = this._browser.activePage;
						var numPages = this._browser.numPages;
						var swipeDistance = touch.getPosition().getX() - this._swipeStartX;		// X touched
						var swipeDistance = touch.getPosition().getY() - this._swipeStartY;
						
						if (swipeDistance > Scale.ios.height(50)) {
							
							if (activePage == 0)
								this._browser.slideToPage(activePage);
							else
								this._browser.slideToPage(activePage-1);
						}
						else if (swipeDistance < Scale.ios.height(-50)) {
							
							if (activePage == numPages - 1)
								this._browser.slideToPage(activePage);
							else
								this._browser.slideToPage(activePage+1);
						}
						else {
							this._browser.slideToPage(this._browser.activePage);
						}
					}
				
					break;
				case touch.Action.Move:
				
					
					if (this._trackingId != touch.getId()) 
					{
						if (this._previoustouchedBlock)
							this._previoustouchedBlock.inactivate();
                        return;
					}
					
					var xChange = Math.abs(this._trackingCurrent.getY() - touch.getPosition().getY()); // X
                    if (xChange < Scale.ios.height(10)) {
                        return;
                    }
					
					this._browser.state = this._browser.State.Swiping;
					
					//if it moved kill the touchedobject
					this._touchedBlock = null;
				
					this._trackingCurrent = touch.getPosition();
					var current = this._browser.getParent().screenToLocal(this._trackingCurrent);
                    var offset = this._trackingOffset;
					
					var tot = current.getY() + offset.getY(); //X
					
					//console.log("-------offset Check " + tot);
					
					if(this._browser._callback!=null && ((current.getX() + offset.getX())>0)){
	 					//return;
					}else if(this._browser._callback!=null && ((current.getX() + offset.getX())<-1600)){
						//return;
					}
					
					var newPosition = new Core.Vector( this._browser.getPosition().getX(),current.getY() + offset.getY());
					this._browser.setPosition(newPosition);
					
					
					
					break;
			}
			
		},
	}),

});
